package com.specter.mvc.view.json;

import java.util.AbstractMap;
import java.util.Map;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * JSON对象的对象类型
 * 
 * @author Liang.Wang
 * @since 2025-04-01 20:20:20
 */
public class JSONObject implements java.io.Serializable {
    private static final long serialVersionUID = 1L;
    private final ObjectNode rootNode;

    @JsonValue
    public ObjectNode toJsonNode() {
        return rootNode;
    }

    public JSONObject() {
        this.rootNode = JsonNodeFactory.instance.objectNode();
    }

    public JSONObject(JsonNode node) {
        if (!(node instanceof ObjectNode)) {
            throw new IllegalArgumentException("Node must be an ObjectNode");
        }
        this.rootNode = (ObjectNode) node;
    }

    public static JSONObject create() {
        return new JSONObject();
    }

    public static JSONObject create(JsonNode node) {
        return new JSONObject(node);
    }

    public static JSONObject create(Map<String, ?> map) {
        return JSONObject.create().put(map);
    }

    /**
     * JSON对象中增加键值
     * 
     * @param key   键
     * @param value 值
     * 
     * @return JSON对象
     */
    public JSONObject put(String key, Object value) {
        if (value == null) {
            rootNode.putNull(key);
        } else if (value instanceof Boolean bv) {
            rootNode.put(key, bv);
        } else if (value instanceof JSONArrays av) {
            rootNode.set(key, av.toJsonNode());
        } else if (value instanceof JSONObject ov) {
            rootNode.set(key, ov.toJsonNode());
        } else {
            rootNode.putPOJO(key, value);
        }
        return this;
    }

    /**
     * 批量增加键值对
     * 
     * @param value 值
     * @return JSON对象
     */
    public JSONObject put(Map<String, ?> value) {
        value.forEach(this::put);
        return this;
    }

    /**
     * 获取值（自动类型转换）
     * 
     * @param key 键
     * @return 获取值
     */
    @SuppressWarnings("unchecked")
    public <T> T get(String key) {
        JsonNode node = rootNode.get(key);
        if (node == null) {
            return null;
        }
        if (node.isArray()) {
            return (T) JSONArrays.create(node);
        }
        if (node.isObject()) {
            return (T) JSONObject.create(node);
        }
        return (T) JSON.mapper.convertValue(node, Object.class);
    }

    /**
     * 获取JSON对象
     * 
     * @param key 键
     * @return JSONObject
     */
    public JSONObject getObject(String key) {
        JsonNode node = rootNode.get(key);
        if (node != null && node.isObject()) {
            return new JSONObject(node);
        }
        return JSONObject.create();
    }

    /**
     * 获取JSON数组
     * 
     * @param key 键
     * @return JSONArrays
     */
    public JSONArrays getArrays(String key) {
        JsonNode node = rootNode.get(key);
        if (node != null && node.isArray()) {
            return new JSONArrays(node);
        }
        return JSONArrays.create();
    }

    /**
     * 转换为Java对象
     * 
     * @param clazz 目标类型
     * @return Java对象
     */
    public <T> T toJavaObject(Class<T> clazz) {
        return JSON.mapper.convertValue(rootNode, clazz);
    }

    /**
     * 转换为JavaMap对象
     * 
     * @return JavaMap对象
     */
    @SuppressWarnings("unchecked")
    public Map<String, Object> toJavaObject() {
        return JSON.mapper.convertValue(rootNode, Map.class);
    }

    /**
     * JSON对象转换为流
     * 
     * @return Stream流（保留JSON结构）
     */
    public Stream<Map.Entry<String, Object>> stream() {
        return StreamSupport
                .stream(Spliterators.spliteratorUnknownSize(rootNode.fields(), Spliterator.ORDERED), false)
                .map(entry -> {
                    String key = entry.getKey();
                    Object value = this.get(key);
                    return new AbstractMap.SimpleEntry<>(key, value);
                });
    }

    /**
     * JSON对象转换为JSON字符串
     * 
     * @return JSON字符串
     */
    public String toJSONString() {
        return rootNode.toString();
    }

    /**
     * JSON对象转换为JSON字符串
     * 
     * @return JSON字符串
     */
    @Override
    public String toString() {
        return rootNode.toString();
    }
}